package com.zenithmind.note.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.common.exception.BusinessException;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.security.SecurityUtils;
import com.zenithmind.note.mapper.NoteMapper;
import com.zenithmind.note.mapper.NoteTagMapper;
import com.zenithmind.note.pojo.dto.NoteTagDTO;
import com.zenithmind.note.pojo.entity.Note;
import com.zenithmind.note.pojo.entity.NoteTag;
import com.zenithmind.note.pojo.query.NoteTagQuery;
import com.zenithmind.note.pojo.vo.NoteTagVO;
import com.zenithmind.note.service.NoteTagService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 笔记标签服务实现
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class NoteTagServiceImpl extends ServiceImpl<NoteTagMapper, NoteTag> implements NoteTagService {

    private final NoteMapper noteMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createTag(NoteTagDTO tagDTO) {
        // 检查标签名称是否已存在
        String userId = SecurityUtils.getCurrentUserId();
        LambdaQueryWrapper<NoteTag> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(NoteTag::getName, tagDTO.getName())
                .eq(NoteTag::getUserId, userId);
        long count = this.count(queryWrapper);
        if (count > 0) {
            throw new BusinessException("标签名称已存在");
        }

        // 创建标签
        NoteTag tag = new NoteTag();
        BeanUtils.copyProperties(tagDTO, tag);
        tag.setUserId(userId);
        tag.setIsSystem(false);
        if (tag.getSort() == null) {
            tag.setSort(0);
        }
        this.save(tag);
        return tag.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateTag(NoteTagDTO tagDTO) {
        // 检查标签是否存在
        NoteTag tag = this.getById(tagDTO.getId());
        if (tag == null) {
            throw new BusinessException("标签不存在");
        }

        // 检查是否有权限修改
        String userId = SecurityUtils.getCurrentUserId();
        if (!userId.equals(tag.getUserId())) {
            throw new BusinessException("无权修改此标签");
        }

        // 检查系统预设标签
        if (Boolean.TRUE.equals(tag.getIsSystem())) {
            throw new BusinessException("系统预设标签不可修改");
        }

        // 检查标签名称是否已存在
        LambdaQueryWrapper<NoteTag> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(NoteTag::getName, tagDTO.getName())
                .eq(NoteTag::getUserId, userId)
                .ne(NoteTag::getId, tagDTO.getId());
        long count = this.count(queryWrapper);
        if (count > 0) {
            throw new BusinessException("标签名称已存在");
        }

        // 更新标签
        BeanUtils.copyProperties(tagDTO, tag);
        this.updateById(tag);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteTag(String id) {
        // 检查标签是否存在
        NoteTag tag = this.getById(id);
        if (tag == null) {
            throw new BusinessException("标签不存在");
        }

        // 检查是否有权限删除
        String userId = SecurityUtils.getCurrentUserId();
        if (!userId.equals(tag.getUserId())) {
            throw new BusinessException("无权删除此标签");
        }

        // 检查系统预设标签
        if (Boolean.TRUE.equals(tag.getIsSystem())) {
            throw new BusinessException("系统预设标签不可删除");
        }

        // 删除标签
        this.removeById(id);
        
        // 注意：这里不检查笔记是否使用此标签，因为标签是通过字符串存储在笔记中的
        // 删除标签后，笔记中的标签字符串不会自动更新，需要在前端处理
    }

    @Override
    public NoteTagVO getTagDetail(String id) {
        NoteTag tag = this.getById(id);
        if (tag == null) {
            throw new BusinessException("标签不存在");
        }

        // 如果不是系统预设标签，检查是否有权限查看
        if (Boolean.FALSE.equals(tag.getIsSystem())) {
            String userId = SecurityUtils.getCurrentUserId();
            if (!userId.equals(tag.getUserId())) {
                throw new BusinessException("无权查看此标签");
            }
        }

        // 查询笔记数量
        int noteCount = countNotesByTag(tag.getName());
        
        // 转换为VO
        NoteTagVO vo = new NoteTagVO();
        BeanUtils.copyProperties(tag, vo);
        vo.setNoteCount(noteCount);
        return vo;
    }

    @Override
    public PageResult<NoteTagVO> tagPage(NoteTagQuery query) {
        // 构建查询条件
        LambdaQueryWrapper<NoteTag> queryWrapper = new LambdaQueryWrapper<>();
        
        // 如果没有指定用户ID，使用当前登录用户
        String userId = query.getUserId();
        if (StringUtils.isBlank(userId)) {
            userId = SecurityUtils.getCurrentUserId();
            query.setUserId(userId);
        }
        
        // 添加查询条件
        queryWrapper.eq(StringUtils.isNotBlank(query.getUserId()), NoteTag::getUserId, query.getUserId())
                .eq(query.getIsSystem() != null, NoteTag::getIsSystem, query.getIsSystem())
                .like(StringUtils.isNotBlank(query.getName()), NoteTag::getName, query.getName())
                .orderByAsc(NoteTag::getSort)
                .orderByDesc(NoteTag::getCreateTime);

        // 分页查询
        Page<NoteTag> page = new Page<>(query.getCurrent(), query.getSize());
        IPage<NoteTag> tagPage = this.page(page, queryWrapper);
        
        // 转换为VO
        List<NoteTagVO> voList = new ArrayList<>();
        if (tagPage.getRecords().isEmpty()) {
            return PageResult.of(voList, tagPage.getTotal(), tagPage.getCurrent(), tagPage.getSize());
        }
        
        // 获取所有标签名称
        List<String> tagNames = tagPage.getRecords().stream()
                .map(NoteTag::getName)
                .collect(Collectors.toList());
        
        // 获取标签使用统计
        Map<String, Integer> tagCountMap = getTagCountMap(tagNames);
        
        // 转换为VO
        for (NoteTag tag : tagPage.getRecords()) {
            NoteTagVO vo = new NoteTagVO();
            BeanUtils.copyProperties(tag, vo);
            Integer noteCount = tagCountMap.getOrDefault(tag.getName(), 0);
            vo.setNoteCount(noteCount);
            voList.add(vo);
        }
        
        return PageResult.of(voList, tagPage.getTotal(), tagPage.getCurrent(), tagPage.getSize());
    }

    @Override
    public List<NoteTagVO> getUserTags(String userId) {
        // 如果没有指定用户ID，使用当前登录用户
        if (StringUtils.isBlank(userId)) {
            userId = SecurityUtils.getCurrentUserId();
        }
        
        // 查询用户的标签列表
        LambdaQueryWrapper<NoteTag> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(NoteTag::getUserId, userId)
                .or()
                .eq(NoteTag::getIsSystem, true)
                .orderByAsc(NoteTag::getSort)
                .orderByDesc(NoteTag::getCreateTime);
        List<NoteTag> tagList = this.list(queryWrapper);
        
        if (tagList.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 获取所有标签名称
        List<String> tagNames = tagList.stream()
                .map(NoteTag::getName)
                .collect(Collectors.toList());
        
        // 获取标签使用统计
        Map<String, Integer> tagCountMap = getTagCountMap(tagNames);
        
        // 转换为VO
        List<NoteTagVO> voList = new ArrayList<>();
        for (NoteTag tag : tagList) {
            NoteTagVO vo = new NoteTagVO();
            BeanUtils.copyProperties(tag, vo);
            Integer noteCount = tagCountMap.getOrDefault(tag.getName(), 0);
            vo.setNoteCount(noteCount);
            voList.add(vo);
        }
        
        return voList;
    }

    @Override
    public List<NoteTagVO> getSystemTags() {
        // 查询系统预设标签
        LambdaQueryWrapper<NoteTag> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(NoteTag::getIsSystem, true)
                .orderByAsc(NoteTag::getSort)
                .orderByDesc(NoteTag::getCreateTime);
        List<NoteTag> tagList = this.list(queryWrapper);
        
        if (tagList.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 获取所有标签名称
        List<String> tagNames = tagList.stream()
                .map(NoteTag::getName)
                .collect(Collectors.toList());
        
        // 获取标签使用统计
        Map<String, Integer> tagCountMap = getTagCountMap(tagNames);
        
        // 转换为VO
        List<NoteTagVO> voList = new ArrayList<>();
        for (NoteTag tag : tagList) {
            NoteTagVO vo = new NoteTagVO();
            BeanUtils.copyProperties(tag, vo);
            Integer noteCount = tagCountMap.getOrDefault(tag.getName(), 0);
            vo.setNoteCount(noteCount);
            voList.add(vo);
        }
        
        return voList;
    }

    @Override
    public List<NoteTagVO> getTagStats(String userId) {
        // 如果没有指定用户ID，使用当前登录用户
        if (StringUtils.isBlank(userId)) {
            userId = SecurityUtils.getCurrentUserId();
        }
        
        // 获取用户的标签列表
        return getUserTags(userId);
    }

    @Override
    public List<Map<String, Object>> getTagCloud(String userId) {
        // 如果没有指定用户ID，使用当前登录用户
        if (StringUtils.isBlank(userId)) {
            userId = SecurityUtils.getCurrentUserId();
        }
        
        // 获取用户的标签列表
        List<NoteTagVO> tags = getUserTags(userId);
        
        // 转换为标签云数据
        return tags.stream().map(tag -> {
            Map<String, Object> map = new HashMap<>(4);
            map.put("id", tag.getId());
            map.put("name", tag.getName());
            map.put("value", tag.getNoteCount());
            map.put("color", tag.getColor());
            return map;
        }).collect(Collectors.toList());
    }
    
    /**
     * 统计指定标签名称的笔记数量
     * 
     * @param tagName 标签名称
     * @return 笔记数量
     */
    private int countNotesByTag(String tagName) {
        LambdaQueryWrapper<Note> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(Note::getTags, tagName);
        return noteMapper.selectCount(queryWrapper).intValue();
    }
    
    /**
     * 获取标签名称和笔记数量的映射
     * 
     * @param tagNames 标签名称列表
     * @return 标签名称和笔记数量的映射
     */
    private Map<String, Integer> getTagCountMap(List<String> tagNames) {
        Map<String, Integer> tagCountMap = new HashMap<>(tagNames.size());
        
        // 查询所有笔记的标签
        LambdaQueryWrapper<Note> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.isNotNull(Note::getTags).ne(Note::getTags, "");
        List<Note> noteList = noteMapper.selectList(queryWrapper);
        
        // 统计每个标签的使用次数
        for (String tagName : tagNames) {
            int count = 0;
            for (Note note : noteList) {
                String tags = note.getTags();
                if (StringUtils.isNotBlank(tags) && containsTag(tags, tagName)) {
                    count++;
                }
            }
            tagCountMap.put(tagName, count);
        }
        
        return tagCountMap;
    }
    
    /**
     * 检查标签字符串是否包含指定标签
     * 
     * @param tags 标签字符串，格式如 "标签1,标签2,标签3"
     * @param tagName 要检查的标签名称
     * @return 是否包含
     */
    private boolean containsTag(String tags, String tagName) {
        if (StringUtils.isBlank(tags) || StringUtils.isBlank(tagName)) {
            return false;
        }
        String[] tagArray = tags.split(",");
        for (String tag : tagArray) {
            if (tagName.equals(tag.trim())) {
                return true;
            }
        }
        return false;
    }
} 